#include "WString.h"
#include "BoardAssembly.h"
#include "mock/EthernetMock.h"
#include "mock/ServiceMock.h"
using ::testing::Return;
using ::testing::Le;
using ::testing::Gt;

class IntegrationTest : public ::testing::Test {
public:
	IntegrationTest() : m(arduino, e, l, "groundFloor"){}
protected:
	EthernetMock e;
	ArduinoMock arduino;
	LoggerMock l;
	
	BoardAssembly m;
	
};

TEST_F(IntegrationTest, soak){
	EXPECT_CALL(e, isInitialized()).
		WillRepeatedly(Return(true));

	EXPECT_CALL(e, sendMessage(String("{\"dbg\":\"mem\", \"val\":\"4000\"}"))).Times(AnyNumber());
	EXPECT_CALL(arduino, availableMem()).WillRepeatedly(Return(4000));

	EXPECT_CALL(arduino, dRead(_)).WillRepeatedly(Return(1));
	EXPECT_CALL(arduino, milliseconds()).WillRepeatedly(Return(1));

	for(int i = 10; i < 20; ++i){
		EXPECT_CALL(arduino, dWrite(i, arduino.HIGHVAL()));
		EXPECT_CALL(arduino, pin(i, arduino.IN()));
		
		EXPECT_CALL(e, isMessageReady()).WillOnce(Return(true));
		EXPECT_CALL(e, getMessage()).WillOnce(Return(String("{\"conf\":\"add\", \"node\":\"groundFloor\", \"type\":\"Montion\", \"name\":\"Montion") + (i-10) + String("\", \"pin\":\"") + i + String("\"}")));
		m.loop();
	}

	for(int i = 0; i < 10; ++i){
		EXPECT_CALL(arduino, dWrite(i, arduino.HIGHVAL()));
		EXPECT_CALL(arduino, pin(i, arduino.IN()));
		
		EXPECT_CALL(e, isMessageReady()).WillOnce(Return(true));
		EXPECT_CALL(e, getMessage()).WillOnce(Return(String("{\"conf\":\"add\", \"node\":\"groundFloor\", \"type\":\"Button\", \"name\":\"Button") + i + String("\", \"pin\":\"") + i + String("\"}")));
		m.loop();
	}


	for(int i = 0; i < 10; ++i){
		EXPECT_CALL(e, isMessageReady()).WillOnce(Return(true));
		EXPECT_CALL(e, getMessage()).WillOnce(
			Return(String("{\"conf\":\"add\", \"node\":\"groundFloor\", \"type\":\"AmbientLight\", \"name\":\"Ambient") + i 
			+ String("\", \"buttonTrigger\":\"Button") + i
			+ String("\", \"montionTrigger\":\"Montion") + i
			+ String("\", \"lightCircuit\":\"Light") + i
			+ String("\"}")));
		m.loop();
	}
	EXPECT_CALL(e, isMessageReady()).WillRepeatedly(Return(false));
	const int montionPins[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9 };
	const int buttonPins[] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };


	
	//EXPECT_CALL(arduino, dRead(ElementsAreArray(buttonPins))).WillRepeatedly(Return(arduino.HIGHVAL()));
	//EXPECT_CALL(arduino, milliseconds()).WillRepeatedly(Return(2000));

	EXPECT_CALL(arduino, dRead(Le(9))).WillRepeatedly(Return(arduino.LOWVAL()));
	EXPECT_CALL(arduino, dRead(Gt(9))).WillRepeatedly(Return(arduino.HIGHVAL()));
	EXPECT_CALL(arduino, milliseconds()).WillRepeatedly(Return(10000));
	m.loop();
	EXPECT_CALL(arduino, dRead(Le(9))).WillRepeatedly(Return(arduino.LOWVAL()));
	EXPECT_CALL(arduino, dRead(Gt(9))).WillRepeatedly(Return(arduino.HIGHVAL()));
	EXPECT_CALL(arduino, milliseconds()).WillRepeatedly(Return(20000));
	for(int i = 0; i < 10; ++i){
		EXPECT_CALL(e, sendMessage(String("{\"event\":\"button\", \"id\":\"Button") + i + String("\", \"state\":\"on\"}")));
		EXPECT_CALL(e, sendMessage(String("{\"cmd\":\"light\", \"id\":\"Light") + i + String("\", \"state\":\"on\"}")));
		EXPECT_CALL(e, sendMessage(String("{\"cmd\":\"light\", \"id\":\"Light") + i + String("\", \"state\":\"off\"}")));
		EXPECT_CALL(e, sendMessage(String("{\"event\":\"montion\", \"id\":\"Montion") + i + String("\"}")));
	}
	m.loop();
	EXPECT_CALL(arduino, dRead(Gt(9))).WillRepeatedly(Return(arduino.LOWVAL()));
	EXPECT_CALL(arduino, dRead(Le(9))).WillRepeatedly(Return(arduino.HIGHVAL()));
	EXPECT_CALL(arduino, milliseconds()).WillRepeatedly(Return(30000));
	m.loop();
	EXPECT_CALL(arduino, milliseconds()).WillRepeatedly(Return(40000));
	m.loop();
	
	EXPECT_CALL(arduino, dRead(Le(9))).WillRepeatedly(Return(arduino.LOWVAL()));
	EXPECT_CALL(arduino, milliseconds()).WillRepeatedly(Return(50000));
	
	m.loop();
	EXPECT_CALL(arduino, milliseconds()).WillRepeatedly(Return(60000));
	for(int i = 0; i < 10; ++i){
		EXPECT_CALL(e, sendMessage(String("{\"event\":\"button\", \"id\":\"Button") + i + String("\", \"state\":\"on\"}")));
		EXPECT_CALL(e, sendMessage(String("{\"cmd\":\"light\", \"id\":\"Light") + i + String("\", \"state\":\"on\"}")));
	}
	
	m.loop();
}
